﻿using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using Loki.Utils;
using Luna.Model.Common;
using Luna.Model.Connector;
using Newtonsoft.Json;

namespace Luna.Google
{
    internal class GoogleGeolocalizer : LokiService, IGeolocalizer
    {
        public class GeoData : IGeoData
        {
            public double Latitude { get; set; }

            public double Longitude { get; set; }
        }

        public class GeoLocation
        {
            public decimal Lat { get; set; }

            public decimal Lng { get; set; }
        }

        public class GeoGeometry
        {
            public GeoLocation Location { get; set; }
        }

        public class GeoResult
        {
            public GeoGeometry Geometry { get; set; }
        }

        public class GeoResponse
        {
            public string Status { get; set; }

            public GeoResult[] Results { get; set; }
        }

        public IGeoData Localize(IGeoAddress address)
        {
            string addressFormat = "{0}, {1}, {2}, {3}";

            string localAdress = string.Format(CultureInfo.InvariantCulture, addressFormat, address.Address, address.ZipCode, address.City, address.Country);

            return Localize(localAdress);
        }

        public IGeoData Localize(string address)
        {
            string urlFormat = "http://maps.googleapis.com/maps/api/geocode/json?address={0}&sensor=false";

            string url = string.Format(urlFormat, address.Replace(" ", "+").ToLowerInvariant());

            WebResponse response = null;
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "GET";
                response = request.GetResponse();
                if (response != null)
                {
                    string str = null;
                    using (Stream stream = response.GetResponseStream())
                    {
                        using (StreamReader streamReader = new StreamReader(stream))
                        {
                            str = streamReader.ReadToEnd();
                        }
                    }

                    GeoResponse geoResponse = JsonConvert.DeserializeObject<GeoResponse>(str);
                    if (geoResponse.Status == "OK")
                    {
                        if (geoResponse.Results.Any())
                        {
                            var match = geoResponse.Results.First();
                            return new GeoData() { Latitude = Convert.ToDouble(match.Geometry.Location.Lat), Longitude = Convert.ToDouble(match.Geometry.Location.Lng) };
                        }
                    }
                    else
                    {
                        Console.WriteLine("JSON response failed, status is '{0}'", geoResponse.Status);
                    }
                }

                return null;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return null;
            }
            finally
            {
                Console.WriteLine("Clean up");
                if (response != null)
                {
                    response.Close();
                    response = null;
                }
            }
        }
    }
}